﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Globalization;


namespace monitor_server
{
    public delegate int form5enable(int l, byte[] Log, int p, byte[] pass);
    public delegate void closing_delegate(Form f);
    public partial class Form1 : Form
    {
        string timeStart;
        int localPort = 38802;                  //Локальный порт
        int log_interval = 2;                   //Задержка между запросами логов (секунды)
        int izmer_interval = 2;                 //Время ожидания ответа на любой запрос к измерителям (секунды)
        int checkParams_interval = 2;           //Задержка между проверкой параметров измерителей (секунды)
        Thread Timer_I;
        Thread checkIzmerParams;
        //Thread Timer_A;
        System.Windows.Forms.Timer I_Timer;
        System.Windows.Forms.Timer checkIzmerParams_Timer;
        //System.Windows.Forms.Timer A_Timer;
        const string version_str = "1.0"; 
        Form5 form5;
        private FormWindowState _OldFormState = FormWindowState.Normal;
        private delegate void text(string str);
        Socket LoginListener;
        public static ManualResetEvent socketevent = new ManualResetEvent(false);
        byte[] cc = { 0x63 };
        byte[] logb = {0x6c, 0x6f, 0x67};
        //private readonly byte[] Buffer = new byte[2048];
        public delegate void RecieveDataHandler(object sender, byte[] data);
        string exe_name = "monitor_server";
        DialogResult Exit_req;
        Form6 form6;
        
        bool f2 = false;
        bool f5 = false;
        bool f6 = false;

        void closing_func(Form f)
        {
            f.Close();
        }

        void func2(bool param)
        {
            f2 = param;
        }

        void func5(bool param)
        {
            f5 = param;
            this.Show();
            button1.Enabled = true;
            this.BringToFront();
        }

        void func6(bool param)
        {
            f6 = param;
        }
                
        private class ConnectionInfo
        {
            public Socket Socket;
            public byte[] Buffer;
            public bool set = false;
            public string login = "unknown";
            public string group = "unknown";
            public string date = "";
        }

        private List<ConnectionInfo> _connections = new List<ConnectionInfo>();

        private List<Analiz> _analizators = new List<Analiz>();

        private class Login
        {
            public int length_v, length_l, length_p;
            public byte[] version, login, password;
        }

        public Form1()
        {
            InitializeComponent();
            int i = DBOperations.RetreiveServerName();
            switch (i)
            {
                case 2:
                    MessageBox.Show("Файл 'resources\\DBServerName.txt' не существует.");
                    break;
                case 3:
                    MessageBox.Show("Файл 'resources\\DBServerName.txt' не доступен для чтения.");
                    break;
                case 4:
                    MessageBox.Show("Некорректное сетевое имя для сервера с БД.");
                    break;
            }
            Izmers.Interval = izmer_interval;
            notify1.MouseDoubleClick += new MouseEventHandler(notifyIcon1_MouseDoubleClick);
            this.Resize += new EventHandler(FormForTray_Resize);
            if (File.Exists(@"resources\prog.ico"))
                this.Icon = new Icon(@"resources\prog.ico");
            else
                this.ShowIcon = false;
            string[] str = Directory.GetFiles(Directory.GetCurrentDirectory());
            i = 0;
            foreach (string st in str)
            {
                if (st.Contains(exe_name + ".exe"))
                    break;
                i++;
            }
            if (i != str.Length)
            {
                curDir.curDirectory = Directory.GetCurrentDirectory();
            }
        }

        void FormForTray_Resize (object sender, EventArgs e)            //Прятать в трей при изменении размера
        {
            if (FormWindowState.Minimized == WindowState)
                {
                    Hide();
                }
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)          //Двойной щелчок по иконке в трее
        {
            if (WindowState == FormWindowState.Normal || WindowState == FormWindowState.Maximized)//если оно развернуто
            {
                _OldFormState = WindowState;
                WindowState = FormWindowState.Minimized;
            }
            else
            {                
                Show();
                WindowState = _OldFormState;
            }
        }

        private void textwrite (string str)
        {
            textBox1.AppendText(str);
        }

        private void Disconnect_handle(IAsyncResult ar)                             //Disconnect
        {
            Socket soc = (Socket)ar.AsyncState;
            soc.EndDisconnect(ar);
            int i = 0;
            foreach (ConnectionInfo con in _connections)
            {
                if (con.Socket.Equals(soc))
                    try
                    {
                        //lock (_connections) _connections.Remove(_connections[i]);
                        break;
                    }
                    catch (Exception)
                    { }
                i++;
            }

            lock (_connections) _connections.Remove(_connections[i]);
        }

        private void Accept_handle(IAsyncResult ar)                             //Accept
        {

            ConnectionInfo connection = new ConnectionInfo();
            Socket listener = (Socket)ar.AsyncState;

            try
            {
                connection.Socket = listener.EndAccept(ar);
                connection.Buffer = new byte[100];
                lock (_connections) _connections.Add(connection);
                connection.Socket.BeginReceive(connection.Buffer, 0, connection.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), connection);
                LoginListener.BeginAccept(new AsyncCallback(Accept_handle), ar.AsyncState);                
            }
            catch (Exception)
            {
                return;
            }            
        }

        private void CloseConnection(ConnectionInfo ci)                     //CloseConnection
        {
            try
            {
                ci.Socket.Shutdown(SocketShutdown.Both);
                ci.Socket.Close();
            }
            catch(Exception)
            {

            }
            try
            {
                string date = DateTime.Now.Year + "-" + DateTime.Now.Month + "-" + DateTime.Now.Day + " " + DateTime.Now.ToLongTimeString();
                DBOperations.DBConnect();
                DBOperations.EventJournalUpdate(ci.login, ci.group, ci.date, date);
                lock (_connections) _connections.Remove(ci);
            }
            catch (Exception)
            { }
                     
        }


        private void ReceiveCallback(IAsyncResult result)                       //Получение пакета
        {
            ConnectionInfo connection = (ConnectionInfo)result.AsyncState;
            int bytesRec = 0;
            try
            {
                bytesRec = connection.Socket.EndReceive(result);
            }
            catch (Exception)
            {
                return;
            }
            byte[] buff = new byte[bytesRec];
            buff = (byte[])connection.Buffer.Clone();
            if (RequestWork(Encoding.UTF8.GetString(buff), connection))
            {
                try
                {
                    connection.Socket.BeginReceive(connection.Buffer, 0, connection.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), connection);
                    return;
                }
                catch (ObjectDisposedException)
                { }
                catch (Exception)
                {
                    CloseConnection(connection);
                    return;
                }
            }
            if (0 != bytesRec)
            {
                byte[] reply = new byte[10];
                EndPoint remoteEP = connection.Socket.RemoteEndPoint;
                text d = textwrite;
                string str = "lol", ipstr;
                ipstr = string.Concat(((IPEndPoint)remoteEP).Address);
                //byte[] bytes = new byte[100];
                //int bytesRec = connection.Socket.Receive(bytes);
                if (bytesRec == 1 && connection.Buffer[0] == cc[0])
                {
                    try
                    {
                        connection.Socket.Send(cc);
                    }
                    catch (Exception)
                    {
                        CloseConnection(connection);
                    }
                }

                //Формирование ответа на запрос доступа в систему
                else
                {
                    Login rec_login = new Login();
                    //rec_login.length_v = (int)connection.Buffer[0];
                    //rec_login.length_l = (int)connection.Buffer[rec_login.length_v + 1];
                    //rec_login.length_p = (int)connection.Buffer[rec_login.length_v + rec_login.length_l + 2];
                    rec_login.length_v = (int)buff[0];
                    if (rec_login.length_v == 99)
                    {
                        CloseConnection(connection);
                        return;
                    }
                    rec_login.length_l = (int)buff[rec_login.length_v + 1];
                    rec_login.length_p = (int)buff[rec_login.length_v + rec_login.length_l + 2];
                    rec_login.version = new byte[rec_login.length_v];
                    rec_login.login = new byte[rec_login.length_l];
                    rec_login.password = new byte[rec_login.length_p];
                    for (int i = 1; i <= rec_login.length_v; i++)
                    {
                        rec_login.version[i - 1] = buff[i];
                    }
                    for (int i = rec_login.length_v + 2; i <= rec_login.length_v + rec_login.length_l + 1; i++)
                    {
                        rec_login.login[i - (rec_login.length_v + 2)] = buff[i];
                    }
                    for (int i = rec_login.length_v + rec_login.length_l + 3; i < bytesRec; i++)
                    {
                        rec_login.password[i - (rec_login.length_v + rec_login.length_l + 3)] = buff[i];
                    }
                    int sendf = 0;
                    string rec_ver = "";
                    rec_ver = Encoding.Default.GetString(rec_login.version);
                    string oblast = server_work.DetermineRegion(ipstr);
                    int access_type = server_work.AccessGainig(rec_login.length_l, rec_login.login, rec_login.length_p, rec_login.password);
                    if (version_str == rec_ver)
                        switch (access_type)
                        {
                            case 1:
                                reply = Encoding.Default.GetBytes("admiaccess");
                                sendf = 1;
                                str = "Администратор";
                                break;
                            case 2:
                                reply = Encoding.Default.GetBytes("useraccess");
                                sendf = 2;
                                str = "Пользователь";
                                break;
                            case 3:
                                reply = Encoding.Default.GetBytes("accessden1");
                                str = "Нет Доступа.";
                                break;
                        }
                    else
                    {
                        reply = Encoding.Default.GetBytes("accessden2");
                        str = "Несоответствие версий.";
                    }
                    if (oblast == "not_found")
                    {
                        reply = Encoding.Default.GetBytes("accessden3");
                        str = "Неизвестный адрес.";
                        sendf = 0;
                    }
                    if (oblast == "false")
                    {
                        reply = Encoding.Default.GetBytes("accessden3");
                        str = "Нет доступа к файлу resources\\clients.csv.";
                        sendf = 0;
                    }
                    string date = DateTime.Now.Year + "-" + DateTime.Now.Month + "-" + DateTime.Now.Day + " " + DateTime.Now.ToLongTimeString();
                    int j = 0;
                    //------Если отключение клиента было без удаления записи из коллекции-------
                    lock (_connections)
                    {
                        foreach (ConnectionInfo con in _connections)
                        {
                            if (con.login == Encoding.Default.GetString(rec_login.login))
                                break;
                            j++;
                        }
                        //Если клиент снова подключился, после непреднамеренного разрыва соединения
                        if (j < _connections.Count)
                        {
                            connection.date = _connections[j].date;
                            connection.login = _connections[j].login;
                            connection.set = _connections[j].set;
                            connection.group = _connections[j].group;
                            _connections.RemoveAt(j);
                        }
                        else
                        {                            
                            connection.date = (string)date.Clone();
                            connection.login = Encoding.Default.GetString(rec_login.login);
                            connection.group = str;  
                        }
                    }                                                    
                    textBox1.Invoke(d, str);
                    if (sendf != 0)
                    {
                        //Формирование ответного массива из данных для ответа
                        if (!connection.set)
                        {
                            //Добавление в БД записи о подключении к серверу
                            DBOperations.DBConnect();
                            if (DBOperations.EventJournalUpdate(connection.login, connection.group, date) == 1)
                                connection.set = true;
                        }
                        byte[] mesLen = new byte[4];
                        byte[] tosend = MakeAccessReply(out mesLen, reply, server_work.DetermineRegion(ipstr), access_type);

                        try
                        {
                            //Длина сообщения
                            connection.Socket.Send(mesLen);
                            //Режим доступа и содержимое файлов
                            connection.Socket.Send(tosend);
                        }
                        catch (Exception)
                        { }
                    }
                    else
                    {
                        byte[] mesLen = new byte[4];
                        mesLen = BitConverter.GetBytes(reply.Length);
                        try
                        {
                            connection.Socket.Send(mesLen);
                            connection.Socket.Send(reply);
                        }
                        catch (Exception)
                        { }
                    }
                }
                try
                {
                    connection.Socket.BeginReceive(connection.Buffer, 0, connection.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), connection);
                }
                catch (ObjectDisposedException)
                { }
                catch (Exception)
                {
                    CloseConnection(connection);
                }
            }
            else CloseConnection(connection);
        }
            //-------------------------------------------------------     

        private bool RequestWork(string message, ConnectionInfo connection)
        {
            string[] split = message.Split('^');
            string req = split[0];
            //split[1] = split[1].Replace('\0', ' ');
            if (split.Length > 1)
                split[1] = split[1].Trim('\0');
            switch (req)
            {
                case "queryIzmers":
                    message = split[1];
                    SelectIzmersResponse(message, connection);
                    return true;

                case "queryAnalyze":
                    message = split[1];
                    SelectAnalizResponse(message, connection);
                    return true;
            }
            return false;
        }

        private void GetLogin()                                                         //Прослушка порта 38802 (Логин)
        {
            //callback = new AsyncCallback(Accept_handle);
            //byte[] bytes = new Byte[50];
            IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 38802);
            LoginListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);        
            LoginListener.Bind(localEP);
            LoginListener.Listen(10);
            //FileStream fl;
            for (int i = 0; i < 10; i++)
            {
                LoginListener.BeginAccept(new AsyncCallback(Accept_handle), LoginListener);
                
            }           
            //socketevent.WaitOne();
        }

        private void tim_I_tick(Object myObject, EventArgs myEventArgs)
        {
            if (Exit_req == DialogResult.Cancel)
                Application.Exit();
            I_Timer.Stop();
            
            if (Timer_I != null)
                if (Timer_I.ThreadState != ThreadState.Aborted && Timer_I.ThreadState != ThreadState.Stopped && Timer_I.ThreadState != ThreadState.Unstarted)
                {
                    I_Timer.Interval = 3000;
                    I_Timer.Start();
                }
                else
                {
                    //I_Timer.Interval = 120000;
                    I_Timer.Interval = log_interval * 1000;
                    I_Timer.Start();
                    //if (!wait_trig)
                    if(!(bool)I_Timer.Tag)
                    {
                        //wait_trig = true;
                        I_Timer.Tag = true;
                        Timer_I = new Thread(new ThreadStart(log_i_thread));
                        Timer_I.Start();
                    }
                    else
                        //wait_trig = false;
                        I_Timer.Tag = false;
                }
            else
            {
                //wait_trig = true;
                I_Timer.Tag = false;
                I_Timer.Start();
                I_Timer.Interval = 3000;
                Timer_I = new Thread(new ThreadStart(log_i_thread));
                Timer_I.Start();                
            }
        }

        private class obl_r
        {
            public string[] obl = {"",""};
        }        

        private void Start_I_Timer()
        {
            //wait_trig = false;            
            I_Timer = new System.Windows.Forms.Timer();
            I_Timer.Tag = false;
            I_Timer.Interval = log_interval * 1000;
            I_Timer.Enabled = true;
            I_Timer.Tick += new EventHandler(tim_I_tick);
            I_Timer.Start();
            
        }

        void checkIzmerParams_Timer_Tick(object sender, EventArgs e)
        {
            checkIzmerParams_Timer.Stop();

            if (checkIzmerParams != null)
                if (checkIzmerParams.ThreadState != ThreadState.Aborted && checkIzmerParams.ThreadState != ThreadState.Stopped && checkIzmerParams.ThreadState != ThreadState.Unstarted)
                {
                    checkIzmerParams_Timer.Interval = 2000;
                    checkIzmerParams_Timer.Start();
                }
                else
                {
                    checkIzmerParams_Timer.Interval = checkParams_interval * 1000;
                    checkIzmerParams_Timer.Start();
                    if (!(bool)checkIzmerParams_Timer.Tag)
                    {
                        checkIzmerParams_Timer.Tag = true;
                        checkIzmerParams = new Thread(new ThreadStart(checkIzmerParams_thread));
                        checkIzmerParams.Start();
                    }
                    else
                        checkIzmerParams_Timer.Tag = false;
                }
            else
            {
                checkIzmerParams_Timer.Tag = false;
                checkIzmerParams_Timer.Start();
                checkIzmerParams_Timer.Interval = 2000;
                checkIzmerParams = new Thread(new ThreadStart(checkIzmerParams_thread));
                checkIzmerParams.Start();
            }
        }

        private void Start_checkIzmerParams_Timer()
        {
            
            checkIzmerParams_Timer = new System.Windows.Forms.Timer();
            checkIzmerParams_Timer.Tag = false;
            checkIzmerParams_Timer.Interval = checkParams_interval * 1000;
            checkIzmerParams_Timer.Enabled = true;
            checkIzmerParams_Timer.Tick += new EventHandler(checkIzmerParams_Timer_Tick);
            checkIzmerParams_Timer.Start();

        }

        //Функция, устанавливающая параметры головного измерителя в области
        private void checkIzmerParams_thread()
        {
            string[] obl;
            int result;
            while (true)
            {
                result = Izmers.activeObls(out obl);
                if (result == 2)
                {
                    notify1.BalloonTipText = "Файл izmers.csv используется другим процессом. Закройте его для корректной работы.";
                    notify1.ShowBalloonTip(5000);
                    return;
                }
                break;
            }
            if (result == 3)
            {
                notify1.BalloonTipText = "В системе нет активных устройств.";
                notify1.ShowBalloonTip(4000);
                return;
            }
            IPAddress[] ips;
            IPAddress[] err = new IPAddress[3] {IPAddress.Parse("0.0.0.0"), IPAddress.Parse("1.1.1.1"), IPAddress.Parse("2.2.2.2")};
            ips = Izmers.izmersIps(obl[0]);
            if (ips[0].Equals(err[1]))
            {
                notify1.BalloonTipText = "Файл izmers.csv не существует.";
                notify1.ShowBalloonTip(4000);
                return;
            }
            if (ips[0].Equals(err[2]))
            {
                notify1.BalloonTipText = "Файл izmers.csv используется другим процессом.";
                notify1.ShowBalloonTip(4000);
                return;
            }

            byte[] mainParams = new byte[9];
            for (int i = 0; i < obl.Length; i++)
            {
                ips = Izmers.izmersIps(obl[i]);
                if (ips[0].Equals(err[0]))
                {
                    notify1.ShowBalloonTip(4000, "Ошибка", "Указан несуществующий измеритель в качестве головного для области '" + obl[i] + "'.", ToolTipIcon.Error);
                    continue;
                }
                //mainParams = Izmers.getParams(ips[0]);
                mainParams = Izmers.getEtalon(ips[0]);
                int count = 0;
                for (int h = 0; h < 9; h++)
                {
                    if (mainParams[h] == 0)
                        count++;
                }
                if (count == 9)
                {
                    notify1.BalloonTipText = "Нет ответа от головного измерителя в области '" + obl[i] + "'";
                    notify1.ShowBalloonTip(5000);
                    return;
                }
                for (int j = 0; j < ips.Length; j++)
                {
                    switch (result = Izmers.checkParams(ips[j], mainParams))
                    {
                        case 1:
                            continue;
                        case 4:
                            //notify1.BalloonTipText = "Нет ответа от измерителя";
                            notify1.ShowBalloonTip(3000, "Нет ответа от измерителя.", " ", ToolTipIcon.Warning);
                            //notify1.ShowBalloonTip(3000);
                            break;
                        case 5:
                            //notify1.BalloonTipText = "Неожиданный ответ от измерителя";
                            //notify1.ShowBalloonTip(3000);
                            break;
                    }
                }
            }
        }

        /*private void Start_A_Timer()
        {
            A_Timer = new System.Windows.Forms.Timer();
            A_Timer.Interval = 5000;
            A_Timer.Enabled = true;
            A_Timer.Start();
            A_Timer.Tick += new EventHandler(timt_A_ick);
        }*/

        private void StopTimer(System.Windows.Forms.Timer tim)
        {
            try
            {
                tim.Stop();
                tim.Dispose();
            }
            catch (NullReferenceException)
            { }
        }

        private void log_i_thread()
        {
            if (!DBOperations.DBConnect())
            {
                notify1.BalloonTipText = "Нет связи с БД.";
                notify1.ShowBalloonTip(3000);
                return;
            }
            Izmers.makeCSV();
            foreach (Analiz an in _analizators)
            {
                try
                {
                    an.makeCSV();
                }
                catch (Exception e)
                {
                    if (e.Message == "err:analyzeLogWriteFailed")
                        notify1.ShowBalloonTip(3000, "Невозможно записать файл с логом анализатора. ",
                                                     "Удостоверьтесь, что программа запущена с правами для записи.", ToolTipIcon.Info);
                }
            }
            if (!Directory.Exists(curDir.curDirectory + @"\resources\logs\"))
                Directory.CreateDirectory(curDir.curDirectory + @"\resources\logs\");
            DirectoryInfo logs = new DirectoryInfo(curDir.curDirectory + @"\resources\logs\");
            string[] logFiles = new string[1];
            logFiles = new string[logs.GetFiles("*.csv").Length];
            for (int i = 0; i < logs.GetFiles("*.csv").Length; i++)
                logFiles[i] = logs + logs.GetFiles("*.csv")[i].ToString();            
            foreach (string st in logFiles)
            {
                DBOperations.UpdateBD_FromCSV(st);
            }
            if (DBOperations.IsConnected)
                DBOperations.CloseConnect();
            int j = 0;
            if(logFiles.Length > 0)
                do
                {
                    if(File.Exists(logFiles[j]))
                        File.Delete(logFiles[j]);
                    j++;
                } while (j < logFiles.Length);
            //notify1.Text = "Обновление логов завершено.";
            //notify1.ShowBalloonTip(3000);
            try
            {
                notify1.ShowBalloonTip(3000, "Обновление логов завершено.", " ", ToolTipIcon.Info);
            }
            catch (Exception)
            {
                return;
            }
            /*if(!Izmers.makeCSV())
                Exit_req = MessageBox.Show("Файл izmers.csv используется другим процессом. Закройте его и повторите попытку.", "", MessageBoxButtons.RetryCancel);
            if (Exit_req == DialogResult.Cancel)
            {
                return;
            }
            else if (Exit_req == DialogResult.Retry)
                log_i_thread();*/
        }

        private void button1_Click(object sender, EventArgs e)              //Start
        {
            int i = 0;
            button2.Enabled = false;
            button1.Visible = false;
            button1.Enabled = false;
            button3.Enabled = true;
            button3.Visible = true;           
            WindowState = FormWindowState.Minimized;
            notify1.Visible = true;
            notify1.Text = "Сервер мониторинга активен";
            if (File.Exists("resources\\prog.ico"))
                notify1.Icon = new Icon("resources\\prog.ico");
            else
            {
                MessageBox.Show("Файл prog.ico не найден.");
                Application.Exit();
            }

            //Создание списков данных об измерителях
            Izmers.createIzmersList();
            server_work.Analizators(ref _analizators);

            Start_I_Timer();
            Start_checkIzmerParams_Timer();

            IPEndPoint localEP = new IPEndPoint(IPAddress.Any, localPort);
            LoginListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            LoginListener.Bind(localEP);
            LoginListener.Listen(10);
            for (i = 0; i < 10; i++)
            {
                LoginListener.BeginAccept(new AsyncCallback(Accept_handle), LoginListener);
            }
            notify1.ShowBalloonTip(3000, "Сервер запущен.", " ", ToolTipIcon.Info);
            string date = DateTime.Now.Year + "-" + DateTime.Now.Month + "-" + DateTime.Now.Day + " " + DateTime.Now.ToLongTimeString();
            timeStart = date;
            DBOperations.DBConnect();
            DBOperations.EventJournalUpdate("Запуск сервера", "", date);
        }

        private void button3_Click(object sender, EventArgs e)              //Stop
        {
            notify1.ShowBalloonTip(3000, "Ожидание завершения выполняющихся операций.", " ", ToolTipIcon.Warning);
            StopTimer(I_Timer);
            StopTimer(checkIzmerParams_Timer);
            try
            {
                Timer_I.Abort();
                Timer_I.Join();
                checkIzmerParams.Abort();
                checkIzmerParams.Join();
            }
            catch (NullReferenceException)
            { }
            button2.Enabled = true;
            notify1.Text = "Сервер мониторинга не запущен";
            button3.Enabled = false;
            
            int i = 0;
            foreach (ConnectionInfo con in _connections)
            {
                con.Socket.Shutdown(SocketShutdown.Both);
                con.Socket.Close();
                i++;
            }
            _connections.RemoveRange(0, i);

            LoginListener.Close();
            
            button3.Visible = false;
            button1.Visible = true;
            button1.Enabled = true;
            notify1.ShowBalloonTip(2500, "Работа сервера приостановлена.", " ", ToolTipIcon.Info);
            string date = DateTime.Now.Year + "-" + DateTime.Now.Month + "-" + DateTime.Now.Day + " " + DateTime.Now.ToLongTimeString();
            DBOperations.DBConnect();
            DBOperations.EventJournalUpdate("Запуск сервера", "", timeStart, date);
        }       

        private void button2_Click(object sender, EventArgs e)
        {            
            if (!f5)
            {
                button1.Enabled = false;
                f5 = !f5;
                form5 = new Form5(new form5enable(server_work.AccessGainig), new formenable(func5));
                form5.Owner = this;
                this.Hide();
                form5.Show();
            }
            else
                MessageBox.Show("Администрирование уже открыто.");
        }
        
        private void Form1_Shown(object sender, EventArgs e)
        {
            button1.PerformClick();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            notify1.ShowBalloonTip(3000, "Ожидание завершения выполняющихся операций.", " ", ToolTipIcon.Warning);
            StopTimer(I_Timer);
            StopTimer(checkIzmerParams_Timer);
            //StopTimer(A_Timer);
            //Timer_A.Abort();
            //Timer_A.Join();
            try
            {
                Timer_I.Abort();
                Timer_I.Join();
                checkIzmerParams.Abort();
                checkIzmerParams.Join();
            }
            catch (Exception)
            { }
            if (f6)
                form6.Close();
            string date = DateTime.Now.Year + "-" + DateTime.Now.Month + "-" + DateTime.Now.Day + " " + DateTime.Now.ToLongTimeString();
            DBOperations.DBConnect();
            DBOperations.EventJournalUpdate("Запуск сервера", "", timeStart, date);
            Application.Exit();
        }

        byte[] MakeAccessReply(out byte[] mesLen, byte[] reply, string oblast, int access)
        {            
            int count = 0;
            byte[][] readf = new byte[6][];
            string[] obls = new string[6];
            readf[0] = File.ReadAllBytes(@"resources\maps\Brest.ini");
            obls[0] = "brest";

            readf[1] = File.ReadAllBytes(@"resources\maps\Vitebsk.ini");
            obls[1] = "viteb";

            readf[2] = File.ReadAllBytes(@"resources\maps\Gomel.ini");
            obls[2] = "gomel";

            readf[3] = File.ReadAllBytes(@"resources\maps\Grodno.ini");
            obls[3] = "grodn";

            readf[4] = File.ReadAllBytes(@"resources\maps\Minsk.ini");
            obls[4] = "minsk";

            readf[5] = File.ReadAllBytes(@"resources\maps\Mogilev.ini");
            obls[5] = "mogil";

            int Num = -1;
            int filesLength = readf[0].Length + readf[1].Length + readf[2].Length + readf[3].Length + readf[4].Length + readf[5].Length;
            

            switch (oblast)
                {
                    case "Брест":
                        oblast = "brest";
                        Num = 0;
                        break;
                    case "Витебск":
                        oblast = "viteb";
                        Num = 1;
                        break;
                    case "Гомель":
                        oblast = "gomel";
                        Num = 2;
                        break;
                    case "Гродно":
                        oblast = "grodn";
                        Num = 3;
                        break;
                    case "Минск":
                        oblast = "minsk";
                        Num = 4;
                        break;
                    case "Могилев":
                        oblast = "mogil";
                        Num = 5;
                        break;
                    default:
                        oblast = "dfind";
                        Num = 4;
                        break;
                }
            byte[] out_obl = new byte[oblast.Length];
            out_obl = Encoding.Default.GetBytes(oblast);
            int messageLength;
            //Отправка всех устройств
            //if (oblast == "minsk")
            if (access == 1)
            {
                messageLength = filesLength + reply.Length + out_obl.Length + 52;
                mesLen = BitConverter.GetBytes(messageLength);
                byte[] tosend = new byte[messageLength];
                //Режим доступа
                for (int i = 0; i < 10; i++)
                {
                    tosend[count] = reply[i];
                    count++;
                }
                //Каждая область
                for (int i = 0; i < 6; i++)
                {
                    out_obl = new byte[obls[i].Length];
                    out_obl = Encoding.Default.GetBytes(obls[i]);
                    //Название области
                    for (int j = 0; j < 5; j++)
                    {
                        tosend[count] = out_obl[j];
                        count++;
                    }
                    //После названия области вставить ':'
                    tosend[count] = (byte)':';
                    count++;
                    //Содержимое файла
                    for (int j = 0; j < readf[i].Length; j++)
                    {
                        tosend[count] = readf[i][j];
                        count++;
                    }
                    //После содержимого вставить ';'
                    tosend[count] = (byte)';';
                    count++;
                }
                return tosend;
            }
            //Отправка одной области
            else
            {
                messageLength = readf[Num].Length + reply.Length + out_obl.Length + 5;
                mesLen = BitConverter.GetBytes(messageLength);
                byte[] tosend = new byte[messageLength];
                //Режим доступа
                for (int i = 0; i < 10; i++)
                {
                    tosend[count] = reply[i];
                    count++;
                }
                //Название области
                for (int i = 0; i < 5; i++)
                {
                    tosend[count] = out_obl[i];
                    count++;
                }
                //После названия области вставить ':'
                tosend[count] = (byte)':';
                count++;
                //Содержимое файла
                for (int i = 0; i < readf[Num].Length; i++)
                {
                    tosend[count] = readf[Num][i];
                    count++;
                }
                //Завершающие символы
                tosend[count] = (byte)';';
                return tosend;
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (!f6)
            {
                f6 = true;
                form6 = new Form6(new formenable(func6));
                //form6.Owner = this;
                form6.Show();
            }
            else
                MessageBox.Show("Журнал уже открыт");
        }

        private void SelectIzmersResponse(string queryMessage, ConnectionInfo connection)
        {
            var toSend = new StringBuilder();
            byte[] reply;
            byte[] replyLen;
            string[] requestResult = DBOperations.SelectIzmers(queryMessage);
            if (requestResult.Length < 1)
            {
                reply = Encoding.UTF8.GetBytes(toSend.ToString());
                replyLen = BitConverter.GetBytes(reply.Length);
                connection.Socket.Send(replyLen);
                connection.Socket.Send(reply);
                return;
            }
            if (requestResult[0].Contains("err:"))
            {
                reply = Encoding.UTF8.GetBytes("err:innererror");
                replyLen = BitConverter.GetBytes(reply.Length);
                connection.Socket.Send(replyLen);
                connection.Socket.Send(reply);
                return;
            }
            toSend.Append(requestResult[0]);
            for (int i = 1; i < requestResult.Length; i++)
            {
                toSend.Append("\n" + requestResult[i]);
            }
            reply = Encoding.UTF8.GetBytes(toSend.ToString());
            replyLen = BitConverter.GetBytes(reply.Length);
            connection.Socket.Send(replyLen);
            connection.Socket.Send(reply);
        }

        private void SelectAnalizResponse(string queryMessage, ConnectionInfo connection)
        {
            var toSend = new StringBuilder();
            byte[] reply;
            byte[] replyLen;
            string[] requestResult = DBOperations.SelectAnalyze(queryMessage);
            if (requestResult.Length < 1)
            {
                reply = Encoding.UTF8.GetBytes(toSend.ToString());
                replyLen = BitConverter.GetBytes(reply.Length);
                try
                {
                    connection.Socket.Send(replyLen);
                    connection.Socket.Send(reply);
                }
                catch (SocketException)
                { }
                return;
            }
            if (requestResult[0].Contains("err:"))
            {
                reply = Encoding.UTF8.GetBytes("err:innererror");
                replyLen = BitConverter.GetBytes(reply.Length);
                try
                {
                    connection.Socket.Send(replyLen);
                    connection.Socket.Send(reply);
                }
                catch (SocketException)
                { }
                return;
            }
            for (int i = 1; i < requestResult.Length; i++)
            {
                toSend.Append("\n" + requestResult[i]);
            }
            reply = Encoding.UTF8.GetBytes(toSend.ToString());
            replyLen = BitConverter.GetBytes(reply.Length);
            try
            {
                connection.Socket.Send(replyLen);
                connection.Socket.Send(reply);
            }
            catch (SocketException)
            {
                return;
            }
        }
    }
}